<?php
namespace app\common\utils;

/**
 * Redis 原生连接
 * \app\common\utils\RedisManager::conn(['select' => 1])->get($key);
 * \app\common\utils\RedisManager::conn(['persistent' => false, 'select' => 1])->get($key);
 * \app\common\utils\RedisManager::conn(['persistent' => false, 'select' => 1])->setEx('test_key', 30, 'test_val');
 * \app\common\utils\RedisManager::conn(['persistent' => false, 'select' => 1])->ttl('test_key');
 * \app\common\utils\RedisManager::conn(['persistent' => false, 'select' => 1])->expire('test_key', 60);
 * \app\common\utils\RedisManager::conn(['persistent' => false, 'select' => 1])->get('test_key');
 */
class RedisManager
{
    private static $redisInstance = null;
    private static $config        = null;

    /**
     * 私有化构造函数，防止外界调用构造新的对象
     */
    private function __construct()
    {}

    /**
     * 获取 Redis 连接的唯一出口
     * @param array $options 连接选项，如 ['persistent' => true, 'select' => 1]
     * @return \Redis
     */
    public static function conn(array $options = []): \Redis
    {
        if (self::$redisInstance === null) {
            self::loadConfig($options);
            self::$redisInstance = self::createRedisInstance($options['persistent'] ?? null);
        }

        // 处理选择数据库逻辑
        if (isset($options['select'])) {
            self::$redisInstance->select((int) $options['select']);
        }

        return self::$redisInstance;
    }

    /**
     * 加载 Redis 配置
     * @param array $options 外部传入的选项
     */
    private static function loadConfig(array $options = []): void
    {
        if (self::$config === null) {
            self::$config = config('cache')['stores']['redis'] ?? [];
        }
        self::$config = array_merge(self::$config, $options);
    }

    /**
     * 创建 Redis 实例
     * @param bool|null $persistent 是否使用持久连接
     * @return \Redis
     */
    private static function createRedisInstance(?bool $persistent = null): \Redis
    {
        $redis      = new \Redis();
        $persistent = $persistent ?? (self::$config['persistent'] ?? false);
        $host       = self::$config['host'];
        $port       = self::$config['port'];
        $timeout    = floatval(self::$config['timeout'] ?? 2.5);

        if ($persistent) {
            $redis->pconnect(
                $host,
                $port,
                $timeout,
                'persistent_id_' . (self::$config['select'] ?? 0)
            );
        } else {
            $redis->connect(
                $host,
                $port,
                $timeout
            );
        }

        if ( ! empty(self::$config['password'])) {
            $redis->auth(self::$config['password']);
        }

        if ( ! empty(self::$config['select'])) {
            $redis->select(self::$config['select']);
        }

        return $redis;
    }

    /**
     * 私有化 __clone 方法，防止实例被克隆
     */
    private function __clone()
    {}

    /**
     * 私有化 __wakeup 方法，防止实例被反序列化
     */
    private function __wakeup()
    {}
}
